﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;

namespace Behavior.Resize
{
    public class ResizeThumb : Thumb
    {
        private Control _item;
        private Canvas _canvas;
        private double _angle;

        public ResizeThumb()
        {
            DragDelta += OnDragDelta;
            DragStarted += OnDragStarted;
        }

        private void OnDragStarted(object sender, DragStartedEventArgs e)
        {
            _item = DataContext as Control;
            if (_item == null) return;
            _canvas = VisualTreeHelper.GetParent(_item) as Canvas;
            if (_canvas == null) return;

            RotateTransform rotateTransform = _item.RenderTransform as RotateTransform;
            if (rotateTransform != null)
            {
                _angle = rotateTransform.Angle * Math.PI / 180.0;
            }
            else
            {
                _angle = 0.0d;
            }

        }

        private void OnDragDelta(object sender, DragDeltaEventArgs e)
        {
            double deltaVertical, deltaHorizontal;
            if (double.IsNaN(_item.Width)) _item.Width = _item.ActualWidth;
            if (double.IsNaN(_item.Height)) _item.Height = _item.ActualHeight;

            switch (VerticalAlignment)
            {
                case VerticalAlignment.Top:
                    deltaVertical = Math.Min(e.VerticalChange, _item.ActualHeight - _item.MinHeight);
                    Canvas.SetTop(_item, Canvas.GetTop(_item) + deltaVertical * Math.Cos(-_angle) + (_item.RenderTransformOrigin.Y * deltaVertical * (1 - Math.Cos(-_angle))));
                    Canvas.SetLeft(_item, Canvas.GetLeft(_item) + deltaVertical * Math.Sin(-_angle) - (_item.RenderTransformOrigin.Y * deltaVertical * Math.Sin(-_angle)));
                    _item.Height -= deltaVertical;
                    break;
                case VerticalAlignment.Bottom:
                    deltaVertical = Math.Min(-e.VerticalChange, _item.ActualHeight - _item.MinHeight);
                    Canvas.SetTop(_item, Canvas.GetTop(_item) + (_item.RenderTransformOrigin.Y * deltaVertical * (1 - Math.Cos(-_angle))));
                    Canvas.SetLeft(_item, Canvas.GetLeft(_item) - deltaVertical * _item.RenderTransformOrigin.Y * Math.Sin(-_angle));
                    _item.Height -= deltaVertical;
                    break;
            }

            switch (HorizontalAlignment)
            {
                case HorizontalAlignment.Left:
                    deltaHorizontal = Math.Min(e.HorizontalChange, _item.ActualWidth - _item.MinWidth);
                    Canvas.SetTop(_item, Canvas.GetTop(_item) + deltaHorizontal * Math.Sin(_angle) - _item.RenderTransformOrigin.X * deltaHorizontal * Math.Sin(_angle));
                    Canvas.SetLeft(_item, Canvas.GetLeft(_item) + deltaHorizontal * Math.Cos(_angle) + (_item.RenderTransformOrigin.X * deltaHorizontal * (1 - Math.Cos(_angle))));
                    _item.Width -= deltaHorizontal;
                    break;
                case HorizontalAlignment.Right:
                    deltaHorizontal = Math.Min(-e.HorizontalChange, _item.ActualWidth - _item.MinWidth);
                    Canvas.SetTop(_item, Canvas.GetTop(_item) - _item.RenderTransformOrigin.X * deltaHorizontal * Math.Sin(_angle));
                    Canvas.SetLeft(_item, Canvas.GetLeft(_item) + (deltaHorizontal * _item.RenderTransformOrigin.X * (1 - Math.Cos(_angle))));
                    _item.Width -= deltaHorizontal;
                    break;
            }
            e.Handled = true;
        }
    }
}
